package com.qingcloud.adminbackend.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qingcloud.adminbackend.constant.WamingConstant;
import com.qingcloud.adminbackend.base.AjaxResult;
import com.qingcloud.adminbackend.base.Vuetable2PageData;
import com.qingcloud.adminbackend.entity.aline.TcpValueCommandDTO;
import com.qingcloud.adminbackend.entity.aline.adapters.ABaseTcpCommandAdapter;
import com.qingcloud.adminbackend.entity.config.SysCommonConfig;
import com.qingcloud.adminbackend.entity.upgrade.EmbeddedBinDTO;
import com.qingcloud.adminbackend.entity.upgrade.UpgradeSpecialDTO;
import com.qingcloud.adminbackend.entity.upgrade.UpgradeSpecialHisDTO;
import com.qingcloud.adminbackend.entity.upgrade.UpgradeSpecialRequest;
import com.qingcloud.adminbackend.mapper.ITdEmbeddedBinMapper;
import com.qingcloud.adminbackend.mapper.ITdUpgradeSpecialHisMapper;
import com.qingcloud.adminbackend.mapper.ITdUpgradeSpecialMapper;
import com.qingcloud.adminbackend.mapper.SysCommonConfigMapper;
import com.qingcloud.adminbackend.service.ISysSensorAlineAitectService;
import com.qingcloud.adminbackend.service.ITdUpgradeSpecialService;
import com.qingcloud.adminbackend.utils.ExcelUtil;
import com.qingcloud.adminbackend.utils.OKHttpUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

@Service
public class ITdUpgradeSpecialServiceImpl implements ITdUpgradeSpecialService {

    @Resource
    private ITdUpgradeSpecialMapper upgradeSpecialMapper;

    @Resource
    private ITdUpgradeSpecialHisMapper upgradeSpecialHisMapper;

    @Resource
    private ISysSensorAlineAitectService sysSensorAlineAitectService;

    @Resource
    private ITdEmbeddedBinMapper embeddedBinMapper;

    @Resource
    private SysCommonConfigMapper configMapper;

    private final String MQTT_COMMAND_API_KEY = "wmiot_command_url";

    private static final Logger logger = LoggerFactory.getLogger(ITdUpgradeSpecialServiceImpl.class);

    /**
     * 分页查询
     *
     * @param upgradeSpecialRequest
     * @return
     */
    public AjaxResult getUpgradeSpecial(UpgradeSpecialRequest upgradeSpecialRequest) {
        List<UpgradeSpecialDTO> usList = upgradeSpecialMapper.search(upgradeSpecialRequest, upgradeSpecialRequest.getOffset(), upgradeSpecialRequest.getPerPage());
        Integer count = upgradeSpecialMapper.count(upgradeSpecialRequest);
        Map<String, Object> resultMap = new HashMap<>(2);
        resultMap.put("data", usList);
        resultMap.put("pagination", new Vuetable2PageData(count.longValue(), upgradeSpecialRequest.getPerPage(), upgradeSpecialRequest.getPage()));
        return new AjaxResult(WamingConstant.SUCCESS, null, resultMap);
    }

    /**
     * 添加
     *
     * @param upgradeSpecial
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public List<TcpValueCommandDTO> addUpgradeSpecial(UpgradeSpecialDTO upgradeSpecial) {
        String equipmentIds = upgradeSpecial.getEquipmentId();
        if (StringUtils.isEmpty(equipmentIds)) {
            logger.debug("Param not contain equipmentId");
            return Collections.emptyList();
        }
        String[] equipmentIdArr = equipmentIds.split(",");
        List<UpgradeSpecialDTO> upgradeSpecialDTOS = new ArrayList<>();
        List<TcpValueCommandDTO> tcpValueCommandDTOS = new ArrayList<>();
        for (String equipmentId : equipmentIdArr) {
            //如果存在于special表中，则移到历史表中，special表中删除
            Integer count = upgradeSpecialMapper.existEqId(equipmentId);
            if (count > 0) {
                //已经存在
                List<UpgradeSpecialHisDTO> param = getUpgradeSpecialHisDTOS(equipmentId);
                upgradeSpecialHisMapper.batchSave(param);
            }
            // 生成新版本
            String oldVersion = upgradeSpecialMapper.findCurrentVersionByEquipmentId(equipmentId);
            UpgradeSpecialDTO upgradeSpecial1 = new UpgradeSpecialDTO();
            upgradeSpecial1.setCurrentVersion(getNewVersion(oldVersion));
            // 批次号
            String bacthNum = generateSurveyTaskCode(upgradeSpecialMapper.findMaxBatchNum());
            upgradeSpecial1.setBatchNum(bacthNum);
            upgradeSpecial1.setRecordStatus("0");
            upgradeSpecial1.setImportTime(new Date());
            upgradeSpecial1.setEquipmentId(equipmentId);
            upgradeSpecial1.setBinId(upgradeSpecial.getBinId());
            upgradeSpecial1.setBeginTime(upgradeSpecial.getBeginTime());
            upgradeSpecial1.setEndTime(upgradeSpecial.getEndTime());
            upgradeSpecial1.setOperator(upgradeSpecial.getOperator());
            upgradeSpecial1.setRemark(upgradeSpecial.getRemark());
            upgradeSpecialDTOS.add(upgradeSpecial1);
            // 发送指令
            EmbeddedBinDTO embeddedBinById = embeddedBinMapper.findEmbeddedBinById(upgradeSpecial.getBinId());
            Map<String, Object> value = new HashMap<>();
            value.put("filePath", embeddedBinById.getFileUrl());
            value.put("md5Val", embeddedBinById.getMd5Code());
            value.put("fileVer", "11.11");
            value.put("stationId", equipmentId);
            value.put("status", Integer.valueOf(embeddedBinById.getRecordStatus()));
            TcpValueCommandDTO tcpValueCommandDTO = new TcpValueCommandDTO();
            tcpValueCommandDTO.setValue(JSON.toJSON(value).toString());
            tcpValueCommandDTO.setCommand(4);
            tcpValueCommandDTO.setEquipmentId(equipmentId);
            tcpValueCommandDTOS.add(tcpValueCommandDTO);
        }
        // 删除原数据
        upgradeSpecialMapper.deleteByEqIds(equipmentIds);
        upgradeSpecialMapper.saveAll(upgradeSpecialDTOS);
        logger.debug("insert into td_upgrade_special success");
        return tcpValueCommandDTOS;
    }

    /**
     * 发送升级指令到物联网后台接口
     *
     * @param tcpValueCommandDTOS
     * @return
     */
    @Override
    public AjaxResult sendUpgradeCommand(List<TcpValueCommandDTO> tcpValueCommandDTOS) {
        // 发送带value指令
        AjaxResult ajaxResult = sysSensorAlineAitectService.command(new ABaseTcpCommandAdapter<List<TcpValueCommandDTO>>(tcpValueCommandDTOS) {
            @Override
            public String getUrl(String baseUrl) {
                return baseUrl + WamingConstant.TCP_UPGRADE_COMMAND;
            }
        });
        if (ajaxResult.getErroCode() == WamingConstant.SUCCESS) {
            return new AjaxResult(WamingConstant.SUCCESS, "添加成功", null);
        }
        logger.debug("Send command ERR, errCode is {} and errMsg is {}", ajaxResult.getErroCode(), ajaxResult.getErroMsg());
        return new AjaxResult(WamingConstant.FAILURE, "调用api失败", null);
    }

    @Override
    public Boolean oldUpgradeCommand(String equipmentId) {
        SysCommonConfig sysCommonConfig = configMapper.findByKey(MQTT_COMMAND_API_KEY);
        String url = sysCommonConfig.getValue() + "/wmiot/ota/upgrade?equipmentIds=" + equipmentId;
        final String result = OKHttpUtil.httpPost(url, "");
        final AjaxResult ajaxResult = JSONObject.parseObject(result, AjaxResult.class);
        if (WamingConstant.SUCCESS.equals(ajaxResult.getErroCode())) {
            return true;
        }
        return false;
    }

    /**
     * 通过ID查找
     *
     * @param id
     * @return
     */
    public AjaxResult getUpgradeSpecialById(String id) {
        UpgradeSpecialDTO us = upgradeSpecialMapper.findUpgradeSpecialById(id);
        return new AjaxResult(WamingConstant.SUCCESS, null, us);
    }

    /**
     * 更新
     *
     * @param upgradeSpecial
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateUpgradeSpecial(UpgradeSpecialDTO upgradeSpecial) {
        Integer flag = upgradeSpecialMapper.update(upgradeSpecial);
        if (flag > 0) {
            return new AjaxResult(WamingConstant.SUCCESS, null, null);
        }
        return new AjaxResult(WamingConstant.FAILURE, null, null);
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteUpgradeSpecial(String[] ids) {
        List<String> idList = Arrays.asList(ids);
        Integer flag = upgradeSpecialMapper.deleteByIdList(idList);
        if (flag > 0) {
            return new AjaxResult(WamingConstant.SUCCESS, "删除成功", null);
        }
        return new AjaxResult(WamingConstant.FAILURE, "删除失败", null);
    }


    private String generateSurveyTaskCode(String maxCode) {
        String today = LocalDate.now().format(WamingConstant.SURVEY_DAY_FORMATTER);
        if (!StringUtils.isEmpty(maxCode) && maxCode.contains(today)) {
            //今天已经有编号了，则递增
            int num = Integer.valueOf(maxCode.split(today)[1]) + 1;
            return "US" + today + String.format("%04d", num);
        } else {
            //今天还没就重新开始
            return "US" + today + "0001";
        }
    }

    public AjaxResult batchImport(MultipartFile excelFile, String userName, String binId) throws Exception {
        AjaxResult result = new AjaxResult();
        XSSFWorkbook workbook2007 = new XSSFWorkbook(excelFile.getInputStream());
        // 取得第一个sheet
        XSSFSheet sheet = workbook2007.getSheetAt(0);
        List<String> equipmentList = Lists.newArrayList();
        // 多少行
        int count = sheet.getLastRowNum();
        XSSFCell cell;
        for (int i = 1; i <= count; i++) {
            // 获取行对象
            XSSFRow row = sheet.getRow(i);
            if (row == null) {// 如果为空，不处理
                continue;
            }
            cell = row.getCell(0);
            if (cell == null) {
                result.setErroMsg("第" + i + "条数据设备编号输入有误!");
                result.setErroCode(3000);
                return result;
            } else {
                String sid = StrUtil.trim(ExcelUtil.getCellValueNew(cell));
                if (StrUtil.isNotBlank(sid)) {
                    if (sid.length() != 8) {
                        result.setErroMsg("第" + i + "条数据设备编号长度异常!");
                        result.setErroCode(3000);
                        return result;
                    }
                    if (equipmentList.contains(sid)) {
                        result.setErroMsg("第" + i + "条数据设备编号存在重复!");
                        result.setErroCode(3000);
                        return result;
                    }
                    Integer temp = upgradeSpecialMapper.existEquipmentId(sid);
                    if (temp <= 0) {
                        result.setErroMsg("第" + i + "条数据设备编号不存在!");
                        result.setErroCode(3000);
                        return result;
                    }
                    equipmentList.add(sid);
                } else {
                    result.setErroMsg("第" + i + "条数据设备编号输入有误!");
                    result.setErroCode(3000);
                    return result;
                }
            }
        }
        String bacthNum = generateSurveyTaskCode(upgradeSpecialMapper.findMaxBatchNum());
        for (String eqId : equipmentList) {
            //是否已经存在于special表中
            Integer tempCount = upgradeSpecialMapper.existEqId(eqId);
            if (tempCount > 0) {
                //已经存在
                List<UpgradeSpecialHisDTO> param = getUpgradeSpecialHisDTOS(eqId);
                upgradeSpecialHisMapper.batchSave(param);
            }
            //删除原数据
            upgradeSpecialMapper.deleteByEqId(eqId);

            UpgradeSpecialDTO upgradeSpecial = new UpgradeSpecialDTO();
            upgradeSpecial.setImportTime(new Date());
            upgradeSpecial.setEquipmentId(eqId);
            upgradeSpecial.setOperator(userName);
            upgradeSpecial.setBinId(binId);
            //生成新版本
            String oldVersion = upgradeSpecialMapper.findCurrentVersionByEquipmentId(upgradeSpecial.getEquipmentId());
            upgradeSpecial.setCurrentVersion(getNewVersion(oldVersion));
            //批次号
            upgradeSpecial.setBatchNum(bacthNum);
            upgradeSpecial.setRecordStatus("0");
            upgradeSpecialMapper.save(upgradeSpecial);
            result.setErroCode(WamingConstant.SUCCESS);
        }
        return result;
    }

    private List<UpgradeSpecialHisDTO> getUpgradeSpecialHisDTOS(String eqId) {
        List<UpgradeSpecialDTO> spList = upgradeSpecialMapper.findByEqId(eqId);
        List<UpgradeSpecialHisDTO> param = new ArrayList<>();
        for (UpgradeSpecialDTO sp : spList) {
            UpgradeSpecialHisDTO temp = new UpgradeSpecialHisDTO();
            temp.setEquipmentId(sp.getEquipmentId());
            temp.setBinId(sp.getBinId());
            temp.setRecordStatus(sp.getRecordStatus());
            temp.setCurrentVersion(sp.getCurrentVersion());
            temp.setBatchNum(sp.getBatchNum());
            temp.setImportTime(sp.getImportTime());
            temp.setBeginTime(sp.getBeginTime());
            temp.setEndTime(sp.getEndTime());
            temp.setOperator(sp.getOperator());
            temp.setRemark(sp.getRemark());
            param.add(temp);
        }
        return param;
    }

    /**
     * 监测输入站点是否存在
     *
     * @param equipmentId
     * @return
     */
    public AjaxResult existEquipmentId(String equipmentId) {
        Integer count = upgradeSpecialMapper.existEquipmentId(equipmentId);
        if (count > 0) {
            return new AjaxResult(WamingConstant.SUCCESS, "", null);
        } else {
            return new AjaxResult(WamingConstant.FAILURE, "", null);
        }
    }

    /**
     * 获取新版本
     */
    private String getNewVersion(String oldVersion) {
        float softwareVersion = 11.11f;
        try {
            float currentVersion = Float.parseFloat(oldVersion);
            if (currentVersion != 0.0f) {
                softwareVersion = Float.parseFloat(oldVersion) + 0.1f;
            }
        } catch (Exception e) {
        }

        String softwareVersionStr = String.valueOf(softwareVersion);

        String[] numberArray = softwareVersionStr.split(".");

        if (numberArray.length != 2) {
            softwareVersionStr = "11.11";
        } else {
            String number1 = numberArray[0];
            String number2 = numberArray[1];
            number1 = number1.length() == 1 ? "1" + number1 : number1.substring(0, 2);
            number2 = number2.length() == 1 ? "1" + number2 : number2.substring(0, 2);
            softwareVersionStr = number1 + "." + number2;
        }
        return softwareVersionStr;
    }
}
